home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 425_01 / tar / zippipe.c < prev    next >
Text File  |  1994-03-29  |  7KB  |  257 lines

  1. #include <stdio.h>
  2. #include "modern.h"
  3. #include "zalloc.h"
  4. #include "zippipe.h"
  5. #include "zipguts.h"
  6. #include "ziposcod.h"
  7. #include "crc32.h"
  8. #ifndef UNIX
  9. #    ifdef M_XENIX
  10. #        define UNIX
  11. #    endif
  12. #    ifdef unix
  13. #        define UNIX
  14. #    endif
  15. #endif
  16. #ifdef UNIX
  17. #    include <time.h>
  18. #endif
  19. #ifdef MSDOS
  20. #    include <dos.h>
  21. #endif
  22.  
  23. #ifdef __TURBOC__
  24.     #pragma warn -rvl
  25. #endif
  26. static unsigned long dostime __ARGS__((void))
  27. {
  28. #ifdef MSDOS
  29. # ifdef __TURBOC__
  30.                 /* inline assembly ha-ha! */
  31.   __emit__(/* all arguments must be words to avoid confusion */
  32.    0x2AB4,      /* mov ah,2Ah - get date */
  33.    0x21CD,      /* int 21h   */
  34.    0xE981,1980, /* sub cx,1980 */
  35.    0xCF88,      /* mov bh,cl */
  36.    0xE7D0,      /* shl bh,1  - pack the year in BX */
  37.    0xD388,      /* mov bl,dl - pack the day  in BX */
  38.    0xD230,      /* xor dl,dl */
  39.    0x03B1,      /* mov cl,03 */
  40.    0xEAD3,      /* shr dx,cl */
  41.    0xD309,      /* or  bx,dx - pack the month -//- */
  42.  
  43.    0x2CB4,      /* mov ah,2Ch get time */
  44.    0x21CD,      /* int 21h   */
  45.    0xC031,      /* xor ax,ax */
  46.    0xCC88,      /* mov ah,cl */
  47.    0x03B1,      /* mov cl,3  */
  48.    0xE8D3,      /* shr ax,cl - pack the minutes in AX */
  49.    0xE5D2,      /* shl ch,cl */
  50.    0xEC08,      /* or  ah,ch - pack the  hours  in AX */
  51.    0xEED0,      /* shr dh,1  */
  52.    0xF008,      /* or  al,dh - pack the seconds in AX */
  53.  
  54.    0xDA89);     /* mov dx,bx - return value in DX:AX */
  55. # else
  56.    uninon REGS r;
  57.    unsigned d;
  58.  
  59.    r.h.ah = 0x2A; /* get date */
  60.    intdos(&r,&r);
  61.    d = ((r.x.cx - 1980) << 9) | (r.h.dh << 5) | r.h.dl;
  62.  
  63.    r.h.ah = 0x2C; /* get time */
  64.    intdos(&r,&r);
  65.    return ((unsigned long)d << 16) |
  66.       (r.h.ch << 11) | (r.h.cl << 5) | (r.h.dh >> 1);
  67. # endif
  68. #else
  69. # ifdef UNIX
  70.    extern long time();
  71.    struct tm *s;
  72.    long t;
  73.  
  74.    (void)time(&t);
  75.    s = gmtime(&t);
  76.    if (s->tm_year < 80) return 0L;
  77.    return ((unsigned long)(s->tm_year - 80) << 25) |
  78.       ((unsigned long)s->tm_mon << 21) | ((unsigned long)s->tm_mday << 16) |
  79.       ((unsigned)s->tm_hour << 11) | (s->tm_min << 5) | (s->tm_sec >> 1);
  80. # else
  81.    /* dummy time stamp */ return 0L;
  82. # endif
  83. #endif
  84. }
  85. #ifdef __TURBOC__
  86.     #pragma warn .rvl
  87. #endif
  88.  
  89. #ifndef zalloc
  90. /* Turbo C malloc() does not allow dynamic allocation of 64K bytes
  91.  * and farmalloc(64K) returns a pointer with nonzero offset, so we
  92.  * must fix the pointer. Warning: the pointer must be saved in its
  93.  * original form in order to free it, use farfree().
  94.  * For MSC, use halloc instead of this function.
  95.  */
  96. void far *zalloc(void far **p, unsigned n, unsigned s)
  97. {
  98.    register unsigned long l;
  99.    l = (unsigned long)(*p = farmalloc((unsigned long)n*s + 15));
  100.    return (void far *)
  101.       ((0xffff0000L & l) + (0xffff0000L & (((0xffffL & l) + 15) << 12)));
  102. }
  103. #endif
  104.  
  105. int zipalloc()
  106. {
  107. #ifdef DYN_ALLOC
  108.    if (ct_alloc() != 0) return ZNOMEM;
  109.    if (lm_alloc() != 0) {
  110.       ct_free(); return ZNOMEM;
  111.    }
  112. #endif
  113.    return 0;
  114. }
  115.  
  116. void zipfree()
  117. {
  118. #ifdef DYN_ALLOC
  119.    lm_free();
  120.    ct_free();
  121. #endif
  122. }
  123.  
  124. static void putlong __ARGS__((ulg));
  125.  
  126. static void putlong(l)
  127. ulg l;
  128. {
  129.    putword((ush)l); putword((ush)(l >> 16));
  130. }
  131.  
  132. static ulg inpsize;
  133. #ifdef DEBUG
  134.        ulg isize;
  135. #endif
  136. static int ziptype;
  137. int deflate_level = 6;
  138. static ulg timestamp;
  139. static ush flags;
  140.  
  141. /* speed options for the general purpose bit flag */
  142. #define FAST 4
  143. #define SLOW 2
  144.  
  145. int zipcreat(putb, ztype, dlevel)
  146. void (*putb)__ARGS__((int));
  147. int ztype, dlevel;
  148. {
  149.    register k;
  150.  
  151.    if (dlevel<1  || dlevel>9 || (ztype!=ZIP_PKW && ztype!=ZIP_GNU))
  152.       return (ziperror = ZUNSUP);
  153.    deflate_level = dlevel;
  154.    flags = dlevel <= 1 ? FAST : dlevel >= 9 ? SLOW : 0;
  155.    ziptype = ztype;
  156.  
  157.    crcbegin();
  158.    bi_init();
  159.    if (ct_init() != 0) return (ziperror = ZNOMEM);
  160.    if ((k=lm_init()) != 0) {
  161. #ifdef DYN_ALLOC
  162.       ct_free();
  163. #endif
  164.       return (ziperror = k);
  165.    }
  166.    ziputbyte = putb;
  167.    /* Write the header to the gzip file */
  168.    /* No extra field, file name or comment; no encryption */
  169.    if (ziptype == ZIP_GNU) {
  170.       putword(GZIP_MAGIC);/* magic header */
  171.       putbyte(DEFLATED);  /* compression method */
  172.       putbyte(0);         /* general flags: nothing */
  173.       putlong(0L);        /* dummy time stamp */
  174.       putbyte(flags);     /* extra flags */
  175.       putbyte(OS_CODE);   /* OS identifier */
  176.    } else {
  177.       putlong(PKW_LOCAL); /* magic header */
  178.       putword(19);        /* version to extract */
  179.       putword(flags|=8);
  180.       putword(DEFLATED);  /* compression method */
  181.       /* Who, the hell, needs in this time stamp? */
  182.       putlong(timestamp = dostime());
  183.       putlong(0L); /* dummy CRC */
  184.       putlong(0L); /* dummy compressed size */
  185.       putlong(0L); /* dummy original size */
  186.       putlong(0L); /* null file name & extra fields */
  187.    }
  188.    inpsize = 0L;
  189.    return 0;
  190. }
  191.  
  192. int zipwrite(buffer, length)
  193. char *buffer; unsigned length;
  194. {
  195.    if (!ziputbyte) return (ziperror=ZNOPEN, -1);
  196.    if (length) {
  197.       updcrc((unsigned char *)buffer, length);
  198.       inpsize += length;
  199.    }
  200.    return deflate_level > 3 ?
  201.             lazy_deflate(buffer, length) :
  202.             fast_deflate(buffer, length);
  203. }
  204.  
  205. long zipclose()
  206. {
  207.    extern unsigned minlookahead;
  208.    register long l = -1;
  209.    ulg clen, crc;
  210.  
  211.    minlookahead = 0; /* indicate end of input */
  212.    /* Flush out any remaining bytes */
  213.    if (zipwrite(NULL,0) != 0) goto end;
  214.    clen = (compressed_len >> 3);
  215.    crc = getcrc();
  216.    if (ziptype == ZIP_GNU) {
  217.       /* Write the crc. & uncompressed size */
  218.       putlong(crc); putlong(inpsize);
  219.    } else {
  220.       /* Write the /data descriptor/ extended locxal header */
  221.       putlong(PKW_EXT); /* signature */
  222.       putlong(crc);     /* CRC */
  223.       putlong(clen);    /* compressed size */
  224.       putlong(inpsize); /* uncompressed size */
  225.       /* Write the central directory entry */
  226.       putlong(PKW_CENTRAL);
  227.       putword((OS_CODE<<8)|20); /* version made by */
  228.       putword(19);      /* version to extract */
  229.       putword(flags);
  230.       putword(DEFLATED);/* compression method */
  231.       putlong(timestamp);
  232.       putlong(crc);     /* CRC */
  233.       putlong(clen);    /* compressed size */
  234.       putlong(inpsize); /* original size */
  235.       putlong(0L);      /* filename & extra field length */
  236.       putword(0);       /* file comment length */
  237.       putword(0);       /* disk number start */
  238.       putword(0);       /* internal file attributes */
  239.       putlong(0L);      /* external file attributes */
  240.       putlong(0L);      /* relative offset of local header */
  241.       /* Finish the central directory */
  242.       putlong(PKW_END);
  243.       putword(0); /* number of this disk */
  244.       putword(0); /* number of the disk with the start of CD */
  245.       putword(1); /* total number of CD entries on this disk */
  246.       putword(1); /* total number of CD entries */
  247.       putlong(46L); /* size of the central directory */
  248.       putlong(30+clen+16); /* offset of start of CD */
  249.       putword(0); /* zipfile comment length */
  250.    }
  251.    l = clen;
  252. end:
  253.    ziputbyte = NULL;
  254.    zipfree();
  255.    return l;
  256. }
  257.